package com.sywl.hibernate;

import java.lang.reflect.Proxy;

import javax.persistence.EntityManager;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

/**
 * 实体管理代理切面
 * 该类定义了一个切入点，和一个处理环绕通知的处理方法
 * 通过spring aop 配置，可以快速的将其插入到系统当中，实现高性能查询
 * 具体使用如下：
 * <pre>
 * {@code
 * <bean id="entityManagerProxyAspect" class="com.sywl.hibernate.EntityManagerProxyAspect"/>
 * <aop:config>
 *   <aop:aspect ref="entityManagerProxyAspect">
 *   	<aop:around method="execute" pointcut="com.sywl.hibernate.EntityManagerProxyAspect.aroundPoint()"/>
 *   </aop:aspect>
 * </aop:config>
 * }
 * </pre>	
 * 通过以上配置，即可以为每一个EntityManager 创建一个代理，实现查询缓存
 * @author 林超
 * @see EntityManagerProxy
 */
@Aspect
public class EntityManagerProxyAspect {
	
	/**
	 * 切入点，拦截EntityManagerFactory的createEntityManager方法
	 */
	@Pointcut("execution(* javax.persistence.EntityManagerFactory.createEntityManager(..))")
	public void aroundPoint(){}
	
	/**
	 * 环绕通知处理方法
	 * 该方法主要是为刚创建的实体管理创建一个代理
	 * @param pj
	 * @return 返回代理对象
	 * @throws Throwable
	 */
	public Object execute(ProceedingJoinPoint pj) throws Throwable {
		EntityManager em = (EntityManager)pj.proceed();
		return Proxy.newProxyInstance(EntityManager.class.getClassLoader(), new Class[]{EntityManager.class}, new EntityManagerProxy(em));
	}
}
